package com.warm.pump.executor.batch;

import com.warm.pump.module.work.bean.po.gen.WorkItem;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.batch.item.database.JdbcCursorItemReader;
import org.springframework.jdbc.core.namedparam.NamedParameterUtils;
import org.springframework.jdbc.support.JdbcUtils;

import java.sql.*;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * 重写JdbcCursorItemReader ，用于支持灵活配置数据抽取
 * Created by guozj on 2017/4/19.
 */
public class CursorItemReader extends JdbcCursorItemReader {
    private static final Logger log = LoggerFactory.getLogger(CursorItemReader.class);


    private PreparedStatement preparedStatement;
    private WorkItem itemDtl;
    private Map<String, Object> condValueMap = new HashMap<>();

    /**
     * 重写afterPropertiesSet 去除 datasource、sql rowMapper不能为空验证
     * @throws Exception
     */
    @Override
    public void afterPropertiesSet() throws Exception {
    }

    @Override
    protected void cleanupOnClose() throws Exception {
        log.debug("[{}]cleanupOnClose....", itemDtl.getItemName());
        JdbcUtils.closeStatement(this.preparedStatement);
    }
    @Override
    protected Object readCursor(ResultSet resultSet, int currentRow) throws SQLException {

        ResultSetMetaData rsMeta = rs.getMetaData();
        LinkedHashMap row = new LinkedHashMap();
        int i = 0;
        for (int size = rsMeta.getColumnCount(); i < size; ++i) {
            String columName = rsMeta.getColumnLabel(i + 1);
            Object value = rs.getObject(i + 1);
            row.put(columName, value);
        }
        return row;
    }



    /**
     * 重写openCursor,支持命名参数sql，支持map参数
     *
     * @param con
     */
    @Override
    protected void openCursor(Connection con) {
        try {
            log.debug("[{}]openCursor....", itemDtl.getItemName());
            //把命名参数sql 改为 占位符 sql
            String psSql = NamedParameterUtils.parseSqlStatementIntoString(itemDtl.getSelectSql());
            //把参数改为 数组
            Object[] objects = NamedParameterUtils.buildValueArray(itemDtl.getSelectSql(), condValueMap);

            log.debug("[{}],执行sql:{}.", itemDtl.getItemName(), itemDtl.getSelectSql());
            log.debug("参数,{}.", condValueMap);
            //JdbcCursorItemReader 中的写法
            if (this.isUseSharedExtendedConnection()) {
                this.preparedStatement = con.prepareStatement(psSql, 1003, 1007, 1);
            } else {
                this.preparedStatement = con.prepareStatement(psSql, 1004, 1007);
            }
            this.preparedStatement.setFetchSize(5000);
            this.preparedStatement.setFetchDirection(ResultSet.FETCH_REVERSE);

            //设置参数
            if (null != objects && objects.length > 0) {
                for (int i = 0; i < objects.length; i++) {
                    preparedStatement.setObject(i + 1, objects[i]);
                }
            }
            this.applyStatementSettings(this.preparedStatement);

            this.rs = this.preparedStatement.executeQuery();
            this.handleWarnings(this.preparedStatement);
        } catch (SQLException var3) {
            log.error("{},打开游标报错:{}", itemDtl.getItemName(), var3);
            this.close();
            throw this.getExceptionTranslator().translate("Executing query", this.getSql(), var3);
        }
    }



    public void setItemDtl(WorkItem itemDtl) {
        this.itemDtl = itemDtl;
    }

    public void setCondValueMap(Map<String, Object> condValueMap) {
        this.condValueMap = condValueMap;
    }
}
